-
Notifications
You must be signed in to change notification settings - Fork 54
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
feat(credentials): store and processing generic app credentials #1466
Conversation
Jenkins BuildsClick to see older builds (7)
|
287b10a
to
cc75811
Compare
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Few queries, looks great!
Maybe we should decide if we plan to merge this, or #1496 first. There would be non-trivial refactoring both ways.
Wow! +696 new lines! 😨 I will need a couple of days to review this. Please, let's keep the PR sizes manageable. Smaller PRs will help us be more agile in reviewing and merging code changes. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
LGTM, maybe we should have instructions for operators to use this feature :)
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I find the code a little convoluted. Please, check my comments.
waku/v2/utils/credentials.nim
Outdated
@@ -0,0 +1,401 @@ | |||
when (NimMajor, NimMinor) < (1, 4): |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I am against adding more stuff under the utils
module.
Please, move the utils/keyfile
and utils/credentials
modules under the waku_rln_relay
module given that at this moment it is the only user of this code.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Agreed to move all keyfile/keystore implementation under a new waku_keystore
module in protocol
. Done in 082043c
waku/v2/utils/credentials.nim
Outdated
type AppKeystore* = object | ||
application*: string | ||
appIdentifier*: string | ||
credentials*: seq[MembershipCredentials] | ||
version*: string | ||
|
||
type | ||
AppKeystoreError = enum | ||
OsError = "keystore error: OS specific error" | ||
IoError = "keystore error: IO specific error" | ||
JsonKeyError = "keystore error: fields not present in JSON" | ||
JsonError = "keystore error: JSON encoder/decoder error" | ||
KeystoreDoesNotExist = "keystore error: file does not exist" | ||
CreateKeystoreError = "Error while creating application keystore" | ||
LoadKeystoreError = "Error while loading application keystore" | ||
CreateKeyfileError = "Error while creating keyfile for credentials" | ||
SaveKeyfileError = "Error while saving keyfile for credentials" | ||
ReadKeyfileError = "Error while reading keyfile for credentials" |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Could you separate the AppKeystore
related code into another module and import and use it here?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Done in 082043c
waku/v2/utils/credentials.nim
Outdated
# Encodes a Membership credential to a byte sequence | ||
proc encode*(credential: MembershipCredentials): seq[byte] = | ||
# TODO: use custom encoding, avoid wordy json | ||
var stringCredential: string | ||
# NOTE: toUgly appends to the string, doesn't replace its contents | ||
stringCredential.toUgly(%credential) | ||
return toBytes(stringCredential) | ||
|
||
# Decodes a byte sequence to a Membership credential | ||
proc decode*(encodedCredential: seq[byte]): KeystoreResult[MembershipCredentials] = | ||
# TODO: use custom decoding, avoid wordy json | ||
try: | ||
# we parse the json decrypted keystoreCredential | ||
let jsonObject = parseJson(string.fromBytes(encodedCredential)) | ||
return ok(to(jsonObject, MembershipCredentials)) | ||
except JsonParsingError: | ||
return err(JsonError) | ||
except Exception: #parseJson raises Exception | ||
return err(OsError) | ||
|
||
# Checks if a JsonNode has all keys contained in "keys" | ||
proc hasKeys*(data: JsonNode, keys: openArray[string]): bool = | ||
return all(keys, proc (key: string): bool = return data.hasKey(key)) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
All the JSON serialization-related code should be in a separate module. Is that possible?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Sure. Separated encoding/decoding of keystore relevant data structures from more general "utils". Done in 082043c
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Thanks for adding it inside the waku_keystore
. I like the new module layout.
There are minor/nitpick details, but in general, LGreatTM ✅
This PR adds a dynamic keystore for membership credential storage and management. The credentials are thought to be generic membership credentials, i.e. associated to a membership contract and membership Merkle tree, and the implementation is not tied to RLN credentials only.
The keystore JSON schema implemented is the one proposed in #1238 (comment).
In short, a keystore is uniquely identified by an application name, app identifier and version strings. Multiple keystores can co-exist in the same file.
Each keystore can contain none or more Membership credentials. Each Membership Credential contains a unique Identity Credential (made of identity trapdoor, nullifier, secret hash and commitment) and none or more Membership Groups. Each Membership Group contains a Membership contract and a membership tree index position. A Membership Contract contains the chain ID and the membership contract address information.
When a Membership credential is added to a certain keystore:
When one or more credentials are added, the keystore is automatically updated to disk (with a backup mechanism to mitigate credentials loss in case of IO errors).
Membership credentials in a certain keystore can be retrieved by none or more filters. These allow to return:
This PR addresses the issues: